[ty] Handle most "deep" mutual typevar constraints#24079
[ty] Handle most "deep" mutual typevar constraints#24079
Conversation
Typing conformance resultsNo changes detected ✅Current numbersThe percentage of diagnostics emitted that were expected errors held steady at 86.38%. The percentage of expected errors that received a diagnostic held steady at 80.68%. The number of fully passing files held steady at 67/133. |
b7d0ca4 to
b341c43
Compare
Memory usage reportSummary
Significant changesClick to expand detailed breakdownprefect
sphinx
trio
flake8
|
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
type-assertion-failure |
0 | 0 | 19 |
invalid-argument-type |
11 | 1 | 4 |
invalid-return-type |
2 | 2 | 1 |
unresolved-attribute |
2 | 0 | 0 |
no-matching-overload |
1 | 0 | 0 |
unsupported-operator |
1 | 0 | 0 |
| Total | 17 | 3 | 24 |
Raw diff (44 changes)
Tanjun (https://github.com/FasterSpeeding/Tanjun)
- tanjun/dependencies/data.py:220:12 error[invalid-return-type] Return type does not match returned value: expected `_T@inject_lc`, found `_T@inject_lc | Coroutine[Any, Any, _T@inject_lc]`
anyio (https://github.com/agronholm/anyio)
+ src/anyio/from_thread.py:378:60 error[invalid-argument-type] Argument to bound method `_spawn_task_from_thread` is incorrect: Expected `Future[T_Retval@start_task_soon | Awaitable[T_Retval@start_task_soon]]`, found `Future[T_Retval@start_task_soon]`
bokeh (https://github.com/bokeh/bokeh)
- src/bokeh/layouts.py:671:16 error[invalid-return-type] Return type does not match returned value: expected `list[L@_parse_children_arg]`, found `list[L@_parse_children_arg | list[L@_parse_children_arg]]`
+ src/bokeh/layouts.py:671:21 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `Iterable[L@_parse_children_arg]`, found `tuple[L@_parse_children_arg | list[L@_parse_children_arg], ...]`
more-itertools (https://github.com/more-itertools/more-itertools)
- more_itertools/recipes.py:1111:18 error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(int | float | complex | ... omitted 3 union elements, int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], /) -> int | float | complex | ... omitted 3 union elements`, found `Overload[(base: int, exp: int, mod: int) -> int, (base: int, exp: Literal[0], mod: None = None) -> Literal[1], (base: int, exp: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], mod: None = None) -> int, (base: int, exp: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], mod: None = None) -> int | float, (base: int, exp: int, mod: None = None) -> Any, (base: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], exp: int | float, mod: None = None) -> int | float, (base: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], exp: int | float, mod: None = None) -> int | float | complex, (base: int | float, exp: int, mod: None = None) -> int | float, (base: int | float, exp: int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], mod: None = None) -> Any, (base: int | float | complex, exp: int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], mod: None = None) -> int | float | complex, [_E_contra, _T_co](base: _SupportsPow2[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _T_co](base: _SupportsPow3NoneOnly[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _M_contra, _T_co](base: _SupportsPow3[_E_contra, _M_contra, _T_co], exp: _E_contra, mod: _M_contra) -> _T_co, (base: _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], exp: int | float, mod: None = None) -> Any, (base: _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], exp: int | float | complex, mod: None = None) -> int | float | complex]`
+ more_itertools/recipes.py:1111:18 error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(int | float | complex | ... omitted 4 union elements, int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], /) -> int | float | complex | ... omitted 4 union elements`, found `Overload[(base: int, exp: int, mod: int) -> int, (base: int, exp: Literal[0], mod: None = None) -> Literal[1], (base: int, exp: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], mod: None = None) -> int, (base: int, exp: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], mod: None = None) -> int | float, (base: int, exp: int, mod: None = None) -> Any, (base: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], exp: int | float, mod: None = None) -> int | float, (base: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], exp: int | float, mod: None = None) -> int | float | complex, (base: int | float, exp: int, mod: None = None) -> int | float, (base: int | float, exp: int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], mod: None = None) -> Any, (base: int | float | complex, exp: int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], mod: None = None) -> int | float | complex, [_E_contra, _T_co](base: _SupportsPow2[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _T_co](base: _SupportsPow3NoneOnly[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _M_contra, _T_co](base: _SupportsPow3[_E_contra, _M_contra, _T_co], exp: _E_contra, mod: _M_contra) -> _T_co, (base: _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], exp: int | float, mod: None = None) -> Any, (base: _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], exp: int | float | complex, mod: None = None) -> int | float | complex]`
mypy (https://github.com/python/mypy)
+ mypy/build.py:4537:38 error[invalid-argument-type] Argument to function `is_sub_path_normabs` is incorrect: Expected `str`, found `Unknown | PathLike[PathLike[Never] | str] | str`
+ mypy/build.py:4539:42 error[invalid-argument-type] Argument to function `is_sub_path_normabs` is incorrect: Expected `str`, found `Unknown | PathLike[PathLike[Never] | str] | str`
+ mypy/dmypy_server.py:1111:39 error[invalid-argument-type] Argument to bound method `listdir` is incorrect: Expected `str`, found `Unknown | PathLike[PathLike[Never] | str] | str`
+ mypy/modulefinder.py:49:16 error[invalid-return-type] Return type does not match returned value: expected `dict[str, tuple[str, ...]]`, found `dict[str, tuple[PathLike[PathLike[Never] | str] | str, ...] | Unknown]`
+ mypy/modulefinder.py:457:67 error[invalid-argument-type] Argument to bound method `find_lib_path_dirs` is incorrect: Expected `tuple[str, ...]`, found `Unknown | tuple[PathLike[PathLike[Never] | str] | str, ...]`
+ mypy/modulefinder.py:466:37 error[invalid-argument-type] Argument to function `os_path_join` is incorrect: Expected `str`, found `Unknown | PathLike[PathLike[Never] | str] | str`
+ mypy/modulefinder.py:470:24 error[no-matching-overload] No overload of function `join` matches arguments
+ mypy/modulefinder.py:478:57 error[invalid-argument-type] Argument to function `os_path_join` is incorrect: Expected `str`, found `Unknown | PathLike[PathLike[Never] | str] | str`
+ mypy/modulefinder.py:489:68 error[invalid-argument-type] Argument to bound method `_find_module_non_stub_helper` is incorrect: Expected `str`, found `Unknown | PathLike[PathLike[Never] | str] | str`
+ mypy/modulefinder.py:504:59 error[invalid-argument-type] Argument to bound method `find_lib_path_dirs` is incorrect: Expected `tuple[str, ...]`, found `Unknown | tuple[PathLike[PathLike[Never] | str] | str, ...]`
+ mypy/modulefinder.py:509:64 error[invalid-argument-type] Argument to bound method `find_lib_path_dirs` is incorrect: Expected `tuple[str, ...]`, found `Unknown | tuple[PathLike[PathLike[Never] | str] | str, ...]`
prefect (https://github.com/PrefectHQ/prefect)
+ src/prefect/_internal/concurrency/api.py:41:16 error[invalid-return-type] Return type does not match returned value: expected `Call[T@cast_to_call]`, found `Call[Awaitable[T@cast_to_call] | T@cast_to_call]`
- src/prefect/input/run_input.py:672:20 error[invalid-return-type] Return type does not match returned value: expected `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]`, found `Unknown | Coroutine[Any, Any, Unknown]`
+ src/prefect/input/run_input.py:672:20 error[invalid-return-type] Return type does not match returned value: expected `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]`, found `T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler] | Coroutine[Any, Any, T@GetAutomaticInputHandler | AutomaticRunInput[T@GetAutomaticInputHandler]]`
scipy (https://github.com/scipy/scipy)
+ scipy/optimize/_trustregion_exact.py:367:40 error[unsupported-operator] Operator `**` is not supported between objects of type `Unknown | SupportsAbs[SupportsDunderLT[Any] | SupportsDunderGT[Any]]` and `Literal[2]`
scipy-stubs (https://github.com/scipy/scipy-stubs)
- tests/sparse/test_construct.pyi:236:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:236:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
- tests/sparse/test_construct.pyi:237:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:237:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
- tests/sparse/test_construct.pyi:238:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `csc_array[complexfloating[_32Bit, _32Bit]]`
+ tests/sparse/test_construct.pyi:238:1 error[type-assertion-failure] Type `csc_array[numpy.bool[builtins.bool]]` does not match asserted type `csc_array[complexfloating[_32Bit, _32Bit]]`
- tests/sparse/test_construct.pyi:239:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `csr_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:239:1 error[type-assertion-failure] Type `csr_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `csr_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
- tests/sparse/test_construct.pyi:240:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:240:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
- tests/sparse/test_construct.pyi:241:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:241:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
- tests/sparse/test_construct.pyi:242:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:242:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
- tests/sparse/test_construct.pyi:244:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[floating[_32Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:244:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[floating[_32Bit], tuple[int, int]]`
- tests/sparse/test_construct.pyi:245:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[float64, tuple[int, int]]`
+ tests/sparse/test_construct.pyi:245:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[float64, tuple[int, int]]`
- tests/sparse/test_construct.pyi:246:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `csc_array[float64]`
+ tests/sparse/test_construct.pyi:246:1 error[type-assertion-failure] Type `csc_array[numpy.bool[builtins.bool]]` does not match asserted type `csc_array[float64]`
- tests/sparse/test_construct.pyi:247:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `csr_array[float64, tuple[int, int]]`
+ tests/sparse/test_construct.pyi:247:1 error[type-assertion-failure] Type `csr_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `csr_array[float64, tuple[int, int]]`
- tests/sparse/test_construct.pyi:248:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[complex128, tuple[int, int]]`
+ tests/sparse/test_construct.pyi:248:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[complex128, tuple[int, int]]`
- tests/sparse/test_construct.pyi:249:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[complex128, tuple[int, int]]`
+ tests/sparse/test_construct.pyi:249:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[complex128, tuple[int, int]]`
- tests/sparse/test_construct.pyi:250:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[complex128, tuple[int, int]]`
+ tests/sparse/test_construct.pyi:250:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[complex128, tuple[int, int]]`
- tests/sparse/test_construct.pyi:268:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[signedinteger[_64Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:268:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[signedinteger[_64Bit], tuple[int, int]]`
- tests/sparse/test_construct.pyi:269:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `csr_array[floating[_32Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:269:1 error[type-assertion-failure] Type `csr_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `csr_array[floating[_32Bit], tuple[int, int]]`
- tests/sparse/test_construct.pyi:270:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:270:1 error[type-assertion-failure] Type `coo_array[numpy.bool[builtins.bool], tuple[int, int]]` does not match asserted type `coo_array[complexfloating[_32Bit, _32Bit], tuple[int, int]]`
- tests/sparse/test_construct.pyi:280:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_matrix[signedinteger[_64Bit]]`
+ tests/sparse/test_construct.pyi:280:1 error[type-assertion-failure] Type `coo_matrix[Unknown]` does not match asserted type `coo_matrix[signedinteger[_64Bit]]`
- tests/sparse/test_construct.pyi:282:1 error[type-assertion-failure] Type `Unknown` does not match asserted type `coo_array[signedinteger[_64Bit], tuple[int, int]]`
+ tests/sparse/test_construct.pyi:282:1 error[type-assertion-failure] Type `coo_array[Unknown, tuple[int, int]]` does not match asserted type `coo_array[signedinteger[_64Bit], tuple[int, int]]`
setuptools (https://github.com/pypa/setuptools)
- setuptools/_distutils/extension.py:123:37 error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(str | bytes | PathLike[str], /) -> str | bytes | PathLike[str]`, found `Overload[(path: str) -> str, (path: bytes) -> bytes, [AnyStr](path: PathLike[AnyStr]) -> AnyStr]`
+ setuptools/_distutils/extension.py:123:37 error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(str | bytes | PathLike[str | bytes], /) -> str | bytes | PathLike[str | bytes | PathLike[str | bytes]]`, found `Overload[(path: str) -> str, (path: bytes) -> bytes, [AnyStr](path: PathLike[AnyStr]) -> AnyStr]`
- setuptools/_vendor/more_itertools/recipes.py:1174:18 error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(int | float | complex | ... omitted 3 union elements, int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], /) -> int | float | complex | ... omitted 3 union elements`, found `Overload[(base: int, exp: int, mod: int) -> int, (base: int, exp: Literal[0], mod: None = None) -> Literal[1], (base: int, exp: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], mod: None = None) -> int, (base: int, exp: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], mod: None = None) -> int | float, (base: int, exp: int, mod: None = None) -> Any, (base: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], exp: int | float, mod: None = None) -> int | float, (base: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], exp: int | float, mod: None = None) -> int | float | complex, (base: int | float, exp: int, mod: None = None) -> int | float, (base: int | float, exp: int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], mod: None = None) -> Any, (base: int | float | complex, exp: int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], mod: None = None) -> int | float | complex, [_E_contra, _T_co](base: _SupportsPow2[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _T_co](base: _SupportsPow3NoneOnly[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _M_contra, _T_co](base: _SupportsPow3[_E_contra, _M_contra, _T_co], exp: _E_contra, mod: _M_contra) -> _T_co, (base: _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], exp: int | float, mod: None = None) -> Any, (base: _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], exp: int | float | complex, mod: None = None) -> int | float | complex]`
+ setuptools/_vendor/more_itertools/recipes.py:1174:18 error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(int | float | complex | ... omitted 4 union elements, int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], /) -> int | float | complex | ... omitted 4 union elements`, found `Overload[(base: int, exp: int, mod: int) -> int, (base: int, exp: Literal[0], mod: None = None) -> Literal[1], (base: int, exp: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], mod: None = None) -> int, (base: int, exp: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], mod: None = None) -> int | float, (base: int, exp: int, mod: None = None) -> Any, (base: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], exp: int | float, mod: None = None) -> int | float, (base: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], exp: int | float, mod: None = None) -> int | float | complex, (base: int | float, exp: int, mod: None = None) -> int | float, (base: int | float, exp: int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], mod: None = None) -> Any, (base: int | float | complex, exp: int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], mod: None = None) -> int | float | complex, [_E_contra, _T_co](base: _SupportsPow2[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _T_co](base: _SupportsPow3NoneOnly[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _M_contra, _T_co](base: _SupportsPow3[_E_contra, _M_contra, _T_co], exp: _E_contra, mod: _M_contra) -> _T_co, (base: _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], exp: int | float, mod: None = None) -> Any, (base: _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], exp: int | float | complex, mod: None = None) -> int | float | complex]`
- setuptools/command/editable_wheel.py:420:19 error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(str | bytes, /) -> str | bytes`, found `Overload[(path: str) -> str, (path: bytes) -> bytes, [AnyStr](path: PathLike[AnyStr]) -> AnyStr]`
+ setuptools/command/editable_wheel.py:420:19 error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(str | bytes | PathLike[str | bytes], /) -> str | bytes | PathLike[str | bytes | PathLike[str | bytes]]`, found `Overload[(path: str) -> str, (path: bytes) -> bytes, [AnyStr](path: PathLike[AnyStr]) -> AnyStr]`
- setuptools/command/editable_wheel.py:420:30 error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `Iterable[str | bytes]`, found `Unknown | list[Path]`
sympy (https://github.com/sympy/sympy)
+ sympy/polys/matrices/sdm.py:1745:36 error[unresolved-attribute] Attribute `items` is not defined on `Iterable[SupportsDunderLT[Any] | SupportsDunderGT[Any]]` in union `Unknown | Iterable[SupportsDunderLT[Any] | SupportsDunderGT[Any]]`
+ sympy/polys/matrices/sdm.py:1954:36 error[unresolved-attribute] Object of type `Iterable[SupportsDunderLT[Any] | SupportsDunderGT[Any]]` has no attribute `items`b341c43 to
8570b68
Compare
|
Moving this to draft while I investigate the perf regression |
8570b68 to
001b57d
Compare
6c54a41 to
ca9105a
Compare
|
The ecosystem hits all look like they are new false positives, due to us still not combining constraint sets across multiple arguments. I've added some mdtests that mimic those new diagnostics. |
| } | ||
| } | ||
|
|
||
| fn add_sequents_for_pair<'db>( |
There was a problem hiding this comment.
Not new in this PR, but in the spirit of trying to ask at least one question at the limit of my understanding: Are there cases where analyzing constraints one-pair-at-a-time isn't sufficient? Like could there be a conclusion that we can only draw by looking at three constraints together?
There was a problem hiding this comment.
As of right now, no, but that is definitely a limitation. So far everything that might require three constraints can proceed in two steps, each of which depends on only two constraints.
That's actually one of the things that I'm bumping into in #22400, since there are currently some patterns that check an equality constraint and some other constraint, and breaking that equality constraint into separate lower and upper bound constraints would mean we'd need to check three constraints at once for that pattern. And I'm loath to introduce a cubic loop like that.
carljm
left a comment
There was a problem hiding this comment.
Accepting with comments -- it seems like the failed-assertion panic case should be fixed before landing.
| // `lower ≤ upper`?") rather than a universal check, because the bounds may mention | ||
| // typevars — e.g., `Sequence[int] ≤ A ≤ Sequence[T]` is satisfiable when `int ≤ T`. | ||
| if lower | ||
| .when_constraint_set_assignable_to(db, upper, builder) |
There was a problem hiding this comment.
Is it safe to use the builder here before we've interned the constraint typevars below? Seems like it might mean that we're operating on an incomplete typevar ordering, leading to inconsistencies later on?
| // Fast path: If L is trivially always assignable to U, there are no derived constraints | ||
| // that we can infer. (This would be handled correctly by the logic below, but this is a | ||
| // useful early return.) | ||
| if when.node == ALWAYS_TRUE { |
There was a problem hiding this comment.
How do you decide when to do this manual check vs when.is_always_satisfied(db)?
There was a problem hiding this comment.
I'll add a comment to this effect, but to answer here as well: (1) This is an early return as an optimization, so it's okay to use the cheaper check. And (2) is_always_satisfied takes into account derived facts, by pruning paths that are impossible because they contain contradictory constraints. Here we're in the middle of building up those derived facts, so it's especially not worth performing the more expensive check if the necessary data is still incomplete.
| } | ||
| // If L is _never_ assignable to U, this constraint would violate transitivity, and should | ||
| // never have been added. | ||
| debug_assert!(!when.is_never_satisfied(db)); |
There was a problem hiding this comment.
Codex came up with this mdtest repro which panics here on debug builds:
from typing import Never, TypeVar, Union
from ty_extensions import ConstraintSet, static_assert
A = TypeVar("A")
T = TypeVar("T")
U = TypeVar("U")
constraints = (
ConstraintSet.range(int, A, Union[T, U])
& ConstraintSet.range(Never, T, str)
& ConstraintSet.range(Never, U, bytes)
)
static_assert(not constraints)The issue seems to be that in ConstraintId::new_node and ConstraintId::intersect, we check that L <= U is existentially satisfiable -- but that check doesn't aim to be comprehensive, it assumes that other constraints (upper bounds of T and U in the above repro) will be independently added to the constraint set. So those checks say "sure, (int <= T <= object) OR (int <= U <= object) looks existentially satisfiable", without considering that actually both int <= T and int <= U are impossible due to the upper bounds of T and U.
But then later here, once typevar bounds are added to the constraint set, we end up handling the derived constraint int <= A <= str | bytes, and panicking on this assertion because int <= str | bytes is never satisfiable.
Codex suggests that this should just be an early return rather than an assertion; not sure if you think a better fix is needed.
It seems like we should reject the above case as never satisfiable, though, not just fail to add sequents for it?
There was a problem hiding this comment.
But then later here, once typevar bounds are added to the constraint set, we end up handling the derived constraint
int <= A <= str | bytes, and panicking on this assertion becauseint <= str | bytesis never satisfiable.Codex suggests that this should just be an early return rather than an assertion; not sure if you think a better fix is needed.
It seems like we should reject the above case as never satisfiable, though, not just fail to add sequents for it?
Ooh this is a great catch. Yes I agree that this should be treated as never satisfiable. In fact, we should notice that int ≤ A ≤ str | bytes is on its own never satisfiable before we ever get to this point. This seems like it could be a more fundamental check to add — if we ever try to create a pair implication where the rhs is false, that's actually a pair impossibility. I think that would end up catching this case.
This is the first step in supporting astral-sh/ty#2045. It handles all variances, but some of the mdtests still have TODOs because they will also require updating
SpecializationBuilderto combine constraint sets across multiple arguments in a call.For the covariant case, we have:
With this PR, the first call is still TODO, but the second call is now revealed correctly.
There are also several lower-level mdtests on the constraint set implementation itself, testing that we actually detect the necessary implications correctly.